package com.atguigu.gmall.search.listener;

import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.pms.entity.*;
import com.atguigu.gmall.search.feign.PmsClient;
import com.atguigu.gmall.search.feign.WmsClient;
import com.atguigu.gmall.search.service.GoodsRepository;
import com.atguigu.gmall.search.vo.Goods;
import com.atguigu.gmall.search.vo.SearchAttrValue;
import com.atguigu.gmall.wms.entity.WareSkuEntity;
import com.rabbitmq.client.Channel;
import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.query.DeleteQuery;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Configuration
@Slf4j
public class RabbitmqListener {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue(
                            name = "gmall.goods.queue",
                            durable = "true"
                    ),
                    exchange = @Exchange(
                            name = "gmall.goods.exchange",
                            durable = "true",
                            type = ExchangeTypes.TOPIC,
                            ignoreDeclarationExceptions = "true"
                    ),
                    key = "goods.*"
            )
    })
    public void goodOperateListener(Message message , Map<String,String> map , Channel channel) {
        try {

            String operate = map.get("operate");
            if("1".equals(operate)){
                String spuId = map.get("spuId");
                //从redis的set中先检查spuId是否导入过
                //新增spu：将数据导入到es中
                this.saveGoods(spuId);//导入成功将spuId缓存到redis的set中
            }else if("2".equals(operate)){
                String skuId = map.get("skuId");
                //执行删除es  sku的业务
//                DeleteQuery deleteQuery = new DeleteQuery();
//                restTemplate.delete(deleteQuery ,Goods.class);
                goodsRepository.deleteById(Long.parseLong(skuId));
//                goodsRepository.save() 如果id存在代表更新 不存在代表新增
            }

            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
        } catch (Exception e) {
            //e.printStackTrace();
            log.error("消息消费异常："+ ExceptionUtils.getStackTrace(e));
            try {
                if(message.getMessageProperties().isRedelivered()){
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
                }else{
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
                }
            } catch (IOException ex) {
//                ex.printStackTrace();
            }
        }

    }

    @Autowired
    PmsClient pmsClient;
    @Autowired
    WmsClient wmsClient;
    @Autowired
    ElasticsearchRestTemplate restTemplate;
    @Autowired
    GoodsRepository goodsRepository;
    public void saveGoods(String sid){
        Long spuId = Long.parseLong(sid);
        //根据spuId查询spu对象
        ResponseVo<SpuEntity> spuResponseVo = pmsClient.querySpuById(spuId);
        if(spuResponseVo.getCode()!=0 || spuResponseVo.getData()==null){
            return;
        }
        SpuEntity spuEntity = spuResponseVo.getData();
        Long brandId = spuEntity.getBrandId();
        Long categoryId = spuEntity.getCategoryId();

        //3、查询每个spu的品牌：逆向工程生成的    pms  BrandController
        ResponseVo<BrandEntity> brandResponseVo = pmsClient.queryBrandById(brandId);

        //4、查询每个spu的分类： 逆向工程生成的  pms  CategoryController
        ResponseVo<CategoryEntity> categoryResponseVo = pmsClient.queryCategoryById(categoryId);

        //5、查询每个spu的检索属性和值：多表联查  需要自定义接口 pms SpuAttrValueController
        ResponseVo<List<SpuAttrValueEntity>> spuAttrsResponseVo = pmsClient.querySpuSearchAttrValues(spuId);

        //6、查询spu的所有的sku集合：接口已存在  修改接口ResponseVo响应的泛型
        ResponseVo<List<SkuEntity>> skusResponseVo = pmsClient.querySkusBySpuId(spuId + "");
        if (skusResponseVo.getCode() == 0 && !Collections.isEmpty(skusResponseVo.getData())) {
            //查询sku集合成功
            List<SkuEntity> skuEntities = skusResponseVo.getData();
            //7、遍历sku集合：
            for (SkuEntity skuEntity : skuEntities) {
                //初始化goods对象
                Goods goods = new Goods();
                Long skuId = skuEntity.getId();
                goods.setSkuId(skuId);
                if (brandResponseVo.getCode() == 0 && brandResponseVo.getData() != null) {
                    //查询品牌成功
                    BrandEntity brandEntity = brandResponseVo.getData();
                    goods.setBrandId(brandEntity.getId());
                    goods.setBrandName(brandEntity.getName());
                    goods.setLogo(brandEntity.getLogo());
                }
                if (categoryResponseVo.getCode() == 0 && categoryResponseVo.getData() != null) {
                    //查询分类成功
                    CategoryEntity categoryEntity = categoryResponseVo.getData();
                    goods.setCategoryId(categoryEntity.getId());
                    goods.setCategoryName(categoryEntity.getName());
                }
                //spu和sku的检索属性和值 都转为SearchAttrValue的对象存到一个集合中
                List<SearchAttrValue> searchAttrValues = new ArrayList<>();
                if (spuAttrsResponseVo.getCode() == 0 && !Collections.isEmpty(spuAttrsResponseVo.getData())) {
                    //查询spu检索属性和值成功
                    for (SpuAttrValueEntity spuAttrValueEntity : spuAttrsResponseVo.getData()) {
                        SearchAttrValue searchAttrValue = new SearchAttrValue();
                        searchAttrValue.setAttrId(spuAttrValueEntity.getAttrId());
                        searchAttrValue.setAttrName(spuAttrValueEntity.getAttrName());
                        searchAttrValue.setAttrValue(spuAttrValueEntity.getAttrValue());
                        searchAttrValues.add(searchAttrValue);
                    }
                }
                //8、查询sku的检索属性和值：多表联查  需要自定义接口 pms SkuAttrValueController
                ResponseVo<List<SkuAttrValueEntity>> skuAttrsResponseVo = pmsClient.querySkuSearchAttrValues(skuId);
                if (skuAttrsResponseVo.getCode() == 0 && !CollectionUtils.isEmpty(skuAttrsResponseVo.getData())) {
                    //sku检索属性和值查询成功
                    for (SkuAttrValueEntity skuAttrValueEntity : skuAttrsResponseVo.getData()) {
                        SearchAttrValue searchAttrValue = new SearchAttrValue();
                        searchAttrValue.setAttrId(skuAttrValueEntity.getAttrId());
                        searchAttrValue.setAttrName(skuAttrValueEntity.getAttrName());
                        searchAttrValue.setAttrValue(skuAttrValueEntity.getAttrValue());
                        searchAttrValues.add(searchAttrValue);
                    }
                }
                //9、查询sku的库存和销量：wms服务  接口已存在  修改接口ResponseVo响应的泛型
                ResponseVo<List<WareSkuEntity>> wareSkusResponseVo = wmsClient.queryWareSkusBySkuId(skuId + "");
                if (wareSkusResponseVo.getCode() == 0 && !CollectionUtils.isEmpty(wareSkusResponseVo.getData())) {
                    //库存销量查询成功
                    List<WareSkuEntity> wareSkuEntities = wareSkusResponseVo.getData();
                    //库存使用的是Boolean类型：任意一个仓库有库存 为true
                    goods.setStore(wareSkuEntities.stream().anyMatch(wareSkuEntity ->
                            wareSkuEntity.getStock()-wareSkuEntity.getStockLocked()>0));
                    //销量存的是数值：多个仓库销量的累加
                    //wareSkuEntities.stream().map(wareSkuEntity -> wareSkuEntity.getSales()) 获取wareSkuEntities集合每个对象的sales属性值存到集合中
                    //.reduce((a,b)->a+b)  将前面集合中的元素累加
                    //.get()  获取累加后的结果
                    goods.setSales(wareSkuEntities.stream().map(wareSkuEntity -> wareSkuEntity.getSales())
                            .reduce((a,b)->a+b).get());

                }
                //10、将每个sku需要的数据封装到Goods对象中
                //将检索属性和值设置给goods
                goods.setSearchAttrValues(searchAttrValues);
                //createTime/defaultImage
                goods.setPrice(skuEntity.getPrice().doubleValue());
                goods.setTitle(skuEntity.getTitle());
                goods.setSubtitle(skuEntity.getSubtitle());
                goods.setCreateTime(spuEntity.getCreateTime());
                goods.setDefaultImage(StringUtils.isEmpty(skuEntity.getDefaultImage())
                        ?"https://img14.360buyimg.com/n7/jfs/t1/143843/25/21094/107919/617a971eE340d3150/b93330bcae736ceb.jpg.avif":skuEntity.getDefaultImage());
                //保存goods对象到es中
                restTemplate.save(goods);
            }
        }
    }
}
